from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_, desc
from datetime import datetime, timedelta
from app.models.xiaohongshu import XiaohongshuAccount, XiaohongshuPublishLog, XiaohongshuToken
from app.crud.base import CRUDBase


class CRUDXiaohongshuAccount(CRUDBase[XiaohongshuAccount, dict, dict]):
    """小红书账号CRUD操作"""
    
    def get_by_nickname(self, db: Session, *, nickname: str) -> Optional[XiaohongshuAccount]:
        """根据昵称获取账号"""
        return db.query(XiaohongshuAccount).filter(XiaohongshuAccount.nickname == nickname).first()
    
    def get_by_account_name(self, db: Session, *, account_name: str) -> Optional[XiaohongshuAccount]:
        """根据账号名获取账号"""
        return db.query(XiaohongshuAccount).filter(XiaohongshuAccount.account_name == account_name).first()
    
    def get_current_account(self, db: Session) -> Optional[XiaohongshuAccount]:
        """获取当前使用的账号"""
        return db.query(XiaohongshuAccount).filter(XiaohongshuAccount.is_current == True).first()
    
    def set_current_account(self, db: Session, *, account_id: int) -> bool:
        """设置当前使用的账号"""
        try:
            # 先将所有账号设为非当前
            db.query(XiaohongshuAccount).update({XiaohongshuAccount.is_current: False})
            
            # 设置指定账号为当前
            db.query(XiaohongshuAccount).filter(XiaohongshuAccount.id == account_id).update({
                XiaohongshuAccount.is_current: True,
                XiaohongshuAccount.updated_at: datetime.utcnow()
            })
            
            db.commit()
            return True
        except Exception:
            db.rollback()
            return False
    
    def update_login_info(self, db: Session, *, account_id: int, cookies: str) -> bool:
        """更新登录信息"""
        try:
            update_data = {
                XiaohongshuAccount.cookies: cookies,
                XiaohongshuAccount.last_login: datetime.utcnow(),
                XiaohongshuAccount.updated_at: datetime.utcnow()
            }
            
            db.query(XiaohongshuAccount).filter(XiaohongshuAccount.id == account_id).update(update_data)
            db.commit()
            return True
        except Exception:
            db.rollback()
            return False
    
    def update_stats(self, db: Session, *, account_id: int, followers: str = None, following: str = None) -> bool:
        """更新统计数据"""
        try:
            update_data = {XiaohongshuAccount.updated_at: datetime.utcnow()}
            
            if followers is not None:
                update_data[XiaohongshuAccount.followers] = followers
            if following is not None:
                update_data[XiaohongshuAccount.following] = following
            
            db.query(XiaohongshuAccount).filter(XiaohongshuAccount.id == account_id).update(update_data)
            db.commit()
            return True
        except Exception:
            db.rollback()
            return False
    
    def get_all_accounts(self, db: Session) -> List[XiaohongshuAccount]:
        """获取所有账号"""
        return db.query(XiaohongshuAccount).all()


class CRUDXiaohongshuPublishLog(CRUDBase[XiaohongshuPublishLog, dict, dict]):
    """小红书发布日志CRUD操作"""
    
    def create_publish_log(self, db: Session, *, account_id: int, post_id: int, title: str, 
                          content: str, images: List[str] = None, tags: str = None) -> XiaohongshuPublishLog:
        """创建发布日志"""
        log = XiaohongshuPublishLog(
            account_id=account_id,
            post_id=post_id,
            title=title,
            content=content,
            images=images,
            tags=tags,
            status="pending"
        )
        db.add(log)
        db.commit()
        db.refresh(log)
        return log
    
    def update_publish_status(self, db: Session, *, log_id: int, status: str, 
                             error_message: str = None, xiaohongshu_post_id: str = None, 
                             xiaohongshu_url: str = None) -> bool:
        """更新发布状态"""
        try:
            update_data = {
                XiaohongshuPublishLog.status: status,
                XiaohongshuPublishLog.updated_at: datetime.utcnow()
            }
            
            if error_message:
                update_data[XiaohongshuPublishLog.error_message] = error_message
            if xiaohongshu_post_id:
                update_data[XiaohongshuPublishLog.xiaohongshu_post_id] = xiaohongshu_post_id
            if xiaohongshu_url:
                update_data[XiaohongshuPublishLog.xiaohongshu_url] = xiaohongshu_url
            if status == "success":
                update_data[XiaohongshuPublishLog.publish_time] = datetime.utcnow()
            
            db.query(XiaohongshuPublishLog).filter(XiaohongshuPublishLog.id == log_id).update(update_data)
            db.commit()
            return True
        except Exception:
            db.rollback()
            return False
    
    def get_by_post_id(self, db: Session, *, post_id: int) -> Optional[XiaohongshuPublishLog]:
        """根据帖子ID获取发布日志"""
        return db.query(XiaohongshuPublishLog).filter(XiaohongshuPublishLog.post_id == post_id).first()
    
    def get_by_account_id(self, db: Session, *, account_id: int, skip: int = 0, limit: int = 100) -> List[XiaohongshuPublishLog]:
        """根据账号ID获取发布日志"""
        return db.query(XiaohongshuPublishLog).filter(
            XiaohongshuPublishLog.account_id == account_id
        ).order_by(desc(XiaohongshuPublishLog.created_at)).offset(skip).limit(limit).all()
    
    def get_recent_logs(self, db: Session, *, days: int = 7, skip: int = 0, limit: int = 100) -> List[XiaohongshuPublishLog]:
        """获取最近的发布日志"""
        since_date = datetime.utcnow() - timedelta(days=days)
        return db.query(XiaohongshuPublishLog).filter(
            XiaohongshuPublishLog.created_at >= since_date
        ).order_by(desc(XiaohongshuPublishLog.created_at)).offset(skip).limit(limit).all()
    
    def get_failed_logs(self, db: Session, *, skip: int = 0, limit: int = 100) -> List[XiaohongshuPublishLog]:
        """获取失败的发布日志"""
        return db.query(XiaohongshuPublishLog).filter(
            XiaohongshuPublishLog.status == "failed"
        ).order_by(desc(XiaohongshuPublishLog.created_at)).offset(skip).limit(limit).all()
    
    def update_stats(self, db: Session, *, log_id: int, views: int = None, likes: int = None, 
                    comments: int = None, shares: int = None) -> bool:
        """更新统计数据"""
        try:
            update_data = {XiaohongshuPublishLog.updated_at: datetime.utcnow()}
            
            if views is not None:
                update_data[XiaohongshuPublishLog.views] = views
            if likes is not None:
                update_data[XiaohongshuPublishLog.likes] = likes
            if comments is not None:
                update_data[XiaohongshuPublishLog.comments] = comments
            if shares is not None:
                update_data[XiaohongshuPublishLog.shares] = shares
            
            db.query(XiaohongshuPublishLog).filter(XiaohongshuPublishLog.id == log_id).update(update_data)
            db.commit()
            return True
        except Exception:
            db.rollback()
            return False


class CRUDXiaohongshuToken(CRUDBase[XiaohongshuToken, dict, dict]):
    """小红书Token CRUD操作"""
    
    def create_token(self, db: Session, *, account_id: int, token_type: str, token_value: str, 
                    expires_at: datetime = None, scope: str = None, token_metadata: Dict[str, Any] = None) -> XiaohongshuToken:
        """创建Token"""
        token = XiaohongshuToken(
            account_id=account_id,
            token_type=token_type,
            token_value=token_value,
            expires_at=expires_at,
            scope=scope,
            token_metadata=token_metadata
        )
        db.add(token)
        db.commit()
        db.refresh(token)
        return token
    
    def get_by_account_and_type(self, db: Session, *, account_id: int, token_type: str) -> Optional[XiaohongshuToken]:
        """根据账号ID和Token类型获取Token"""
        return db.query(XiaohongshuToken).filter(
            and_(
                XiaohongshuToken.account_id == account_id,
                XiaohongshuToken.token_type == token_type,
                XiaohongshuToken.is_active == True
            )
        ).first()
    
    def get_active_tokens(self, db: Session, *, account_id: int) -> List[XiaohongshuToken]:
        """获取账号的所有有效Token"""
        return db.query(XiaohongshuToken).filter(
            and_(
                XiaohongshuToken.account_id == account_id,
                XiaohongshuToken.is_active == True,
                or_(
                    XiaohongshuToken.expires_at.is_(None),
                    XiaohongshuToken.expires_at > datetime.utcnow()
                )
            )
        ).all()
    
    def update_last_used(self, db: Session, *, token_id: int) -> bool:
        """更新Token最后使用时间"""
        try:
            db.query(XiaohongshuToken).filter(XiaohongshuToken.id == token_id).update({
                XiaohongshuToken.last_used: datetime.utcnow(),
                XiaohongshuToken.updated_at: datetime.utcnow()
            })
            db.commit()
            return True
        except Exception:
            db.rollback()
            return False
    
    def deactivate_token(self, db: Session, *, token_id: int) -> bool:
        """停用Token"""
        try:
            db.query(XiaohongshuToken).filter(XiaohongshuToken.id == token_id).update({
                XiaohongshuToken.is_active: False,
                XiaohongshuToken.updated_at: datetime.utcnow()
            })
            db.commit()
            return True
        except Exception:
            db.rollback()
            return False
    
    def cleanup_expired_tokens(self, db: Session) -> int:
        """清理过期的Token"""
        try:
            count = db.query(XiaohongshuToken).filter(
                and_(
                    XiaohongshuToken.expires_at.isnot(None),
                    XiaohongshuToken.expires_at < datetime.utcnow()
                )
            ).update({XiaohongshuToken.is_active: False})
            db.commit()
            return count
        except Exception:
            db.rollback()
            return 0


# 创建CRUD实例
xiaohongshu_account_crud = CRUDXiaohongshuAccount(XiaohongshuAccount)
xiaohongshu_publish_log_crud = CRUDXiaohongshuPublishLog(XiaohongshuPublishLog)
xiaohongshu_token_crud = CRUDXiaohongshuToken(XiaohongshuToken)